
package panels;

import core.COINCOMOComponent;
import core.COINCOMOSubSystem;
import core.COINCOMOSystem;
import core.COINCOMOUnit;
import database.COINCOMOComponentManager;
import database.COINCOMOSubSystemManager;
import database.COINCOMOSystemManager;
import extensions.COINCOMOTreeNode;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import main.COINCOMO;
import main.GlobalMethods;
import main.Icons;

/**
 *
 * @author Raed Shomali
 */
public class HierarchyPanel extends JPanel implements ActionListener , TreeSelectionListener , MouseListener
{
    // Popup Menu
    JPopupMenu popup = new JPopupMenu();
    
    // Popup Items
    JMenuItem addUnitMenuItem = new JMenuItem( "Add" );
//    JMenuItem copyUnitMenuItem = new JMenuItem("Copy");
    JMenuItem deleteUnitMenuItem = new JMenuItem( "Delete" );
    JMenuItem renameUnitMenuItem = new JMenuItem( "Rename" );
    
    // Tool Bar
    JToolBar toolBar = new JToolBar();
    
    // Tool Bar Items
    public static JButton addSubSystemButton = new JButton();
//    public static JButton copySubSystemButton = new JButton();
    public static JButton deleteSubSystemButton = new JButton();
    public static JButton addComponentButton = new JButton();
//    public static JButton copyComponentButton = new JButton();
    public static JButton deleteComponentButton = new JButton();
    
    // Tree
    // Define a new Node Tree, give it a name and a type
    public static COINCOMOTreeNode root = null ;
    public static JTree tree = new JTree( root );
    public static JScrollPane treeScroller = new JScrollPane( tree );

    // Keep Track of selected Node
    public static COINCOMOTreeNode selectedNode = null;

    public HierarchyPanel()
    {
        // Popup Menu
        addUnitMenuItem.addActionListener( this );
//        copyUnitMenuItem.addActionListener( this );
        deleteUnitMenuItem.addActionListener( this );
        renameUnitMenuItem.addActionListener( this );

        renameUnitMenuItem.setIcon( Icons.RENAME_ICON ) ;
        
        // Toolbar Buttons
        addSubSystemButton.setIcon( Icons.ADD_SUBSYSTEM_ICON );
 //       copySubSystemButton.setIcon( Icons.COPY_ICON );
        deleteSubSystemButton.setIcon( Icons.DELETE_SUBSYSTEM_ICON );
        addComponentButton.setIcon( Icons.ADD_COMPONENT_ICON );
 //       copyComponentButton.setIcon( Icons.COPY_ICON );
        deleteComponentButton.setIcon( Icons.DELETE_COMPONENT_ICON );

        addSubSystemButton.setEnabled( false );
 //       copySubSystemButton.setEnabled( false );
        deleteSubSystemButton.setEnabled( false );
        addComponentButton.setEnabled( false );
 //       copyComponentButton.setEnabled( false );
        deleteComponentButton.setEnabled( false );

        addSubSystemButton.addActionListener( this );
 //       copySubSystemButton.addActionListener( this );
        deleteSubSystemButton.addActionListener( this );
        addComponentButton.addActionListener( this );
 //       copyComponentButton.addActionListener( this );
        deleteComponentButton.addActionListener( this );

        addSubSystemButton.setBorderPainted( false );
 //      copySubSystemButton.setBorderPainted( false );
        deleteSubSystemButton.setBorderPainted( false );
        addComponentButton.setBorderPainted( false );
 //       copyComponentButton.setBorderPainted( false );
        deleteComponentButton.setBorderPainted( false );

        addSubSystemButton.setFocusPainted( false );
 //       copySubSystemButton.setFocusPainted( false );
        deleteSubSystemButton.setFocusPainted( false );
        addComponentButton.setFocusPainted( false );
 //       copyComponentButton.setFocusPainted( false );
        deleteComponentButton.setFocusPainted( false );

        addSubSystemButton.setBackground( Color.decode( "#FFFFFF" ) );
 //       copySubSystemButton.setBackground( Color.decode( "#FFFFFF" ) );
        deleteSubSystemButton.setBackground( Color.decode( "#FFFFFF" ) );
        addComponentButton.setBackground( Color.decode( "#FFFFFF" ) );
 //       copyComponentButton.setBackground( Color.decode( "#FFFFFF" ) );
        deleteComponentButton.setBackground( Color.decode( "#FFFFFF" ) );

        toolBar.setBackground( Color.decode( "#FFFFFF" ) );
        toolBar.setBorder( BorderFactory.createEtchedBorder() );

        toolBar.add( addSubSystemButton );
 //       toolBar.add( copySubSystemButton );
        toolBar.add( deleteSubSystemButton );
        toolBar.add( addComponentButton );
 //       toolBar.add ( copyComponentButton );
        toolBar.add( deleteComponentButton );

        // ---------------------------------------------------------------
        // Tree

        tree.addMouseListener( this );
        tree.addTreeSelectionListener( this );
        tree.setBorder( BorderFactory.createMatteBorder( 5 , 5 , 5 , 5 , Color.WHITE ) );
        tree.setCellRenderer( new extensions.COINCOMOTreeCellRenderer() );

        this.setLayout( new BorderLayout() );
        this.add( toolBar , BorderLayout.NORTH );
        this.add( treeScroller );
    }

    public void actionPerformed( ActionEvent e )
    {
        // If nothing is selected ...
        if ( selectedNode == null )
        {
            // Exit
            return;
        }

        // If Popup's Items Are Selected
        if ( e.getSource() == addUnitMenuItem )
        {
            // If System is Selected ..
            if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSystem )
            {
                addUnit( COINCOMOSubSystemManager.insertSubSystem( selectedNode.getCOINCOMOUnit().getUnitID() ) ) ;
            }
            else // Sub System is Selected ...
            {
                addUnit( COINCOMOComponentManager.insertComponent( selectedNode.getCOINCOMOUnit().getUnitID() ) ) ;
                COINCOMOComponentManager.insertCompCocotProject( selectedNode.getCOINCOMOUnit().getUnitID() );
                //COINCOMOComponentManager.insertCompCocotProject( selectedNode.getCOINCOMOUnit().getUnitID() );
            }
        }
  /*      
        else if ( e.getSource() == copyUnitMenuItem )
        {
            //if Sub system is selected
            if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSubSystem)
            {
                copyUnit( COINCOMOSubSystemManager.insertSubSystem(selectedNode.getCOINCOMOUnit().getUnitID()));
            }
        }
        
  */      
        else if ( e.getSource() == deleteUnitMenuItem )
        {
            // If Subsystem is Selected
            if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSubSystem )
            {
                deleteUnit( selectedNode.getCOINCOMOUnit() ) ;
            }
            else    // If Component Is Selected
            {
                deleteUnit( selectedNode.getCOINCOMOUnit() ) ;
            }
        }
        else if ( e.getSource() == renameUnitMenuItem )
        {
            String result = JOptionPane.showInputDialog( COINCOMO.application , "Please enter the new name:" ) ;
            
            // If Not Empty
            if( result != null && !result.trim().equals( "" ) )
            {
                // Update Name of the COINCOMO Unit Inside the Tree Node
                selectedNode.getCOINCOMOUnit().setName( result );
                
                // Update Name of the Tree Node on the Tree
                selectedNode.setUserObject( result );
                ((DefaultTreeModel)tree.getModel()).nodeChanged(selectedNode) ;

                // Refresh
                HierarchyPanel.tree.repaint() ;
                
                // Create a Thread
                SwingUtilities.invokeLater( new Runnable()
                {
                    public void run()
                    {
                        // Save in Database ...
                        if( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSystem )
                        {
                            COINCOMOSystemManager.updateSystem( (COINCOMOSystem) selectedNode.getCOINCOMOUnit() ) ;
                        }
                        else if( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSubSystem )
                        {
                            COINCOMOSubSystemManager.updateSubSystem( (COINCOMOSubSystem) selectedNode.getCOINCOMOUnit() ) ;
                        }
                        else
                        {
                            COINCOMOComponentManager.updateComponent( (COINCOMOComponent) selectedNode.getCOINCOMOUnit() ) ;
                        }
                        
                        GlobalMethods.updateStatusBar( "New name has been saved." );
                    }
                });
            }
            
            // Update Overview Tab
            OverviewsAndGraphsPanel.updateOverviewTabWith( selectedNode.getCOINCOMOUnit() );
            //OverviewsAndGraphsPanel.updateCosysmoTabWith(selectedNode.getCOINCOMOUnit());

        }
        // Tool Buttons Are Selected ...
        else if ( e.getSource() == addSubSystemButton )
        {
            addUnit( COINCOMOSubSystemManager.insertSubSystem( selectedNode.getCOINCOMOUnit().getUnitID() ) );
        }
  /*      
        else if ( e.getSource() == copySubSystemButton )
        {
            copyUnit( COINCOMOSubSystemManager.insertSubSystem( selectedNode.getCOINCOMOUnit().getUnitID() ) );
        }
  */      
        else if ( e.getSource() == deleteSubSystemButton )
        {
            deleteUnit( selectedNode.getCOINCOMOUnit() );
        }
        else if ( e.getSource() == addComponentButton )
        {
            addUnit( COINCOMOComponentManager.insertComponent( selectedNode.getCOINCOMOUnit().getUnitID() ) );
        	COINCOMOComponentManager.insertCompCocotProject( selectedNode.getCOINCOMOUnit().getUnitID() );
            //COINCOMOComponentManager.insertCompCocotProject( selectedNode.getCOINCOMOUnit().getUnitID() );
        }
 /*               
        else if ( e.getSource() == copyComponentButton )
        {
            copyUnit( COINCOMOSubSystemManager.insertSubSystem( selectedNode.getCOINCOMOUnit().getUnitID() ) );
        }
 */       
        else    // Delete Component
        {
            deleteUnit( selectedNode.getCOINCOMOUnit() );
        }
    }

    public void valueChanged( TreeSelectionEvent e )
    {
        selectedNode = (COINCOMOTreeNode) (e.getPath().getLastPathComponent());

        // Set Everything to Disabled
        addSubSystemButton.setEnabled( false );
 //       copySubSystemButton.setEnabled( false );
        deleteSubSystemButton.setEnabled( false );
        addComponentButton.setEnabled( false );
 //       copyComponentButton.setEnabled( false );
        deleteComponentButton.setEnabled( false );

        // Clear Popup Menu
        popup.removeAll();

        if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSystem )
        {
            addSubSystemButton.setEnabled( true );

            // Update Popup Menu Items Accordingly ..
            addUnitMenuItem.setText( "Add Sub System" );
            addUnitMenuItem.setIcon( Icons.ADD_SUBSYSTEM_ICON ) ;

            popup.add( addUnitMenuItem );
            popup.addSeparator();
            popup.add( renameUnitMenuItem );
        }
        else if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOSubSystem )
        {
            addComponentButton.setEnabled( true );
            
   /*         
            copySubSystemButton.setEnabled ( true );
            
   */       
            deleteSubSystemButton.setEnabled( true );

            // Update Popup Menu Items Accordingly ..            
            addUnitMenuItem.setText( "Add Component" );
            addUnitMenuItem.setIcon( Icons.ADD_COMPONENT_ICON ) ;
            
  /*          copyUnitMenuItem.setText( "Copy Sub System" );
            copyUnitMenuItem.setIcon( Icons.COPY_ICON );
  */          
            deleteUnitMenuItem.setText( "Delete Sub System" );
            deleteUnitMenuItem.setIcon( Icons.DELETE_SUBSYSTEM_ICON ) ;
            
            popup.add( addUnitMenuItem );
 /*           
            popup.add( copyUnitMenuItem );
   */                     
            popup.add( deleteUnitMenuItem );
            popup.addSeparator();
            popup.add( renameUnitMenuItem );
        }
        else if ( selectedNode.getCOINCOMOUnit() instanceof COINCOMOComponent )
        {
 //           copyComponentButton.setEnabled( true );
            deleteComponentButton.setEnabled( true );

            // Update Popup Menu Items Accordingly ..
 //           copyUnitMenuItem.setText( "Copy Component" );
 //           copyUnitMenuItem.setIcon( Icons.COPY_ICON );
            deleteUnitMenuItem.setText( "Delete Component" );
            deleteUnitMenuItem.setIcon( Icons.DELETE_COMPONENT_ICON ) ;

 //           popup.add( copyUnitMenuItem );
            popup.add( deleteUnitMenuItem );
            popup.addSeparator();
            popup.add( renameUnitMenuItem );
        }

        // Update the Overview Tab
        if( selectedNode.getCOINCOMOUnit() != null )
        {
            OverviewsAndGraphsPanel.updateOverviewTabWith( selectedNode.getCOINCOMOUnit() );
        }

      }

    public void mouseClicked( MouseEvent e )
    {
        TreePath treePath = tree.getPathForLocation( e.getX() , e.getY() );

        if ( treePath != null )
        {
            // Highlight the Selected Node through its Tree Path ...
            tree.setSelectionPath( treePath );

            // Is Right Click Clicked ? And On a Tree Node ?
            if ( e.getButton() == 3 )
            {
                // Show the Popup Menu
                popup.show( e.getComponent() , e.getX() , e.getY() );
            }
        }
    }

    /**
     * 
     * @param unitType is used to determine the type of the unit being added
     */
    public static void addUnit( COINCOMOUnit unitType )
    {
        DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();

        // Define a new Node Tree, give it a name and a type
        COINCOMOTreeNode subUnitNode = new COINCOMOTreeNode( unitType );

        // Insert Internally
        selectedNode.getCOINCOMOUnit().addSubUnit( subUnitNode.getCOINCOMOUnit() );

        // Insert in Tree
        treeModel.insertNodeInto( subUnitNode , selectedNode , selectedNode.getChildCount() );

        // Show Newly Added Node, and Select It
        tree.scrollPathToVisible( new TreePath( subUnitNode.getPath() ) );
        tree.setSelectionPath( new TreePath( subUnitNode.getPath() ) );

        // Status Has To be Updated After Selection Happens ...
        // Since "selectedNode" is the node that is 'currently' highlighted
        GlobalMethods.updateStatusBar( "One " + (unitType instanceof COINCOMOSubSystem ? "Subsystem" : "Component") + " has been added." );
    }
    
 /*   
    public static void copyUnit( COINCOMOUnit unitType)
    {
        
        
    }
  */
    public static void deleteUnit( COINCOMOUnit unitType )
    {
        DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();

        // Get Parent of Node to Be Deleted
        COINCOMOTreeNode parentNode = (COINCOMOTreeNode) selectedNode.getParent();

        // Remove Internally
        parentNode.getCOINCOMOUnit().getListOfSubUnits().remove( unitType.getUnitID() );

        // Thread Variables ...
        final long copyOfID = unitType.getUnitID();
        final boolean isSubSystem = (unitType instanceof COINCOMOSubSystem);
        final String unitName = unitType.getName();

        // Create a Thread
        SwingUtilities.invokeLater( new Runnable()
        {
            public void run()
            {
                // Remove From Database
                if ( isSubSystem )
                {
                    COINCOMOSubSystemManager.deleteSubSystem( copyOfID );
                }
                else
                {
                    COINCOMOComponentManager.deleteComponent( copyOfID );
                }


                GlobalMethods.updateStatusBar( (isSubSystem ? "Subsystem " : "Component ") + unitName + " has been deleted." );
            }

        } );

        // Remove node
        treeModel.removeNodeFromParent( selectedNode );

        // Select Parent Node
        tree.setSelectionPath( new TreePath( parentNode.getPath() ) );
    }

    public void mousePressed( MouseEvent e )
    {
    }

    public void mouseReleased( MouseEvent e )
    {
    }

    public void mouseEntered( MouseEvent e )
    {
    }

    public void mouseExited( MouseEvent e )
    {
    }
}
